package com.yuhuofei2021.spring.boot.weather.service.implement;

import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuhuofei2021.spring.boot.weather.entity.WeatherResponse;
import com.yuhuofei2021.spring.boot.weather.service.WeatherDataService;

/**
 * 
 * @description WeatherDataService实现类
 * @author yuhuofei2021
 * @date 2021年7月1日
 */
@Service
public class WeatherDataServiceImplement implements WeatherDataService {
	
	public  final static String  MAIN= "http://wthrcdn.etouch.cn/weather_mini?";
	
	private final static Logger logger = LoggerFactory.getLogger(WeatherDataServiceImplement.class);
	
	//redis缓存数据过期超时时间
	private final static long Time_OUT = 1800L; 
	
	@Resource
	private RestTemplate restTemplate;
	
	@Resource
	private StringRedisTemplate stringRedisTemplate;
	
	@Override
	public WeatherResponse getDataByCityId(String cityId) {
		String  cityIdUrl= MAIN + "citykey=" +cityId;
		logger.info("根据城市码，查询天气==============");
		return this.httpRequestMethod(cityIdUrl);
	}

	@Override
	public WeatherResponse getDataByCityName(String cityName) {
		String  cityNameUrl= MAIN + "city=" +cityName;
		logger.info("根据城市名，查询天气==============");
		return this.httpRequestMethod(cityNameUrl);
	}
	
	/**
	 * 
	 * @description 请求http接口的公用方法
	 * 1、先查redis中是否有缓存数据，如果有，则直接返回结果
	 * 2、如果redis中没有查到缓存数据，则请求外部天气查询接口，并将查询结果写入到redis中
	 * @author yuhuofei2021
	 * @date 2021年7月1日 
	 * @param urlString
	 * @return
	 */
	private WeatherResponse httpRequestMethod(String urlString) {
		String repBody = null;
		WeatherResponse response =null;
		ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
		
		//查询redis中是否有缓存数据
		if(stringRedisTemplate.hasKey(urlString)) {
			//redis中有缓存数据，直接获取使用
			logger.info("redis中有缓存数据，获取使用==========");
			repBody = ops.get(urlString);
		} else {
			//redis中没有缓存数据，请求接口获取天气数据
			logger.info("redis中没有缓存数据，请求外部天气查询接口==========");
			ResponseEntity<String> repString = restTemplate.getForEntity(urlString, String.class);
			
			if (200 == repString.getStatusCodeValue()) {
				repBody = repString.getBody();
				logger.info("外部天气查询接口返回结果：" + repBody);
			}
			
			//将接口返回数据写入redis
			logger.info("将接口返回结果写入redis中！");
			ops.set(urlString, repBody, Time_OUT, TimeUnit.SECONDS);
		}
		
		try {//将接口返回的String类型报文转换成WeatherResponse对象
			response = new ObjectMapper().readValue(repBody,WeatherResponse.class);
		} catch (Exception e) {
			logger.info("字符串转为对象处理异常！");
		}
		return response;
	}

	@Override
	public void syncDataByCityId(String cityId) {
		String url= MAIN + "citykey=" +cityId;
		this.saveWeatherData(url);
	}
	
	/**
	 * 
	 * @description 把天气数据写到缓存中
	 * @author yuhuofei2021
	 * @date 2021年9月21日 
	 * @param urlString
	 */
	private void saveWeatherData(String urlString) {

		String repBody = null;
		ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
		
		//请求接口获取天气数据
		logger.info("请求外部天气查询接口==========");
		ResponseEntity<String> repString = restTemplate.getForEntity(urlString, String.class);
		
		if (200 == repString.getStatusCodeValue()) {
			repBody = repString.getBody();
			logger.info("外部天气查询接口返回结果：" + repBody);
		}
		
		//将接口返回数据写入redis
		logger.info("将接口返回结果写入redis中！");
		ops.set(urlString, repBody, Time_OUT, TimeUnit.SECONDS);

	} 
}
